package com.geng.connect;

import com.geng.cluster.ClusterStrategy;
import com.geng.cluster.engine.ClusterEngine;
import com.geng.dto.InvokerService;
import com.geng.dto.ProviderService;
import com.geng.invoker.NettyChannelFactory;
import com.geng.zkORdc.IRegisterCenter4Invoker;
import com.geng.zkORdc.RegisterCenter;
import org.apache.commons.collections.MapUtils;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

public class ZKConnect implements IConnectStrategy {

    /**
     * 需要调用的服务的接口
     */
    private Class<?> targetInterface;

    /**
     * 负载均衡策略
     */
    private String clusterStrategy;

    /**
     * socket
     */
    private ProviderService providerService;

    public ZKConnect(Builder builder) {
        this.targetInterface = builder.targetInterface;
        this.clusterStrategy = builder.clusterStrategy;
        this.providerService = builder.providerService;
    }

    @Override
    public ProviderService creatProvider(Method method) {
        // 服务接口名称
        String serviceKey = targetInterface.getName();
        //获取某个接口的服务提供者列表
        IRegisterCenter4Invoker registerCenter4Consumer = RegisterCenter.singleton();
        List<ProviderService> providerServices = registerCenter4Consumer.getServiceMetaDataMap4Consume().get(serviceKey);
        //根据软负载策略,从服务提供者列表选取本次调用的服务提供者
        ClusterStrategy clusterStrategyService = ClusterEngine.queryClusterStrategy(clusterStrategy);
        ProviderService providerService = clusterStrategyService.select(providerServices);
        //复制一份服务提供者信息
        ProviderService newProvider = providerService.copy();
        //设置本次调用服务的方法以及接口
        newProvider.setServiceMethod(method);
        newProvider.setServiceItf(targetInterface);
        return newProvider;
    }

    @Override
    public void registeChannel(ChannelPara para) {
        String remoteAppKey = para.getRemoteAppKey();
        String groupName = para.getGroupName();
        IRegisterCenter4Invoker registerCenter4Consumer = RegisterCenter.singleton();
        if (!registerCenter4Consumer.isInit()) {
            synchronized (registerCenter4Consumer) {
                if (!registerCenter4Consumer.isInit()) {
                    //初始化服务提供者列表到本地缓存
                    registerCenter4Consumer.initProviderMap(remoteAppKey, groupName);
                    //初始化Netty Channel
                    Map<String, List<ProviderService>> providerMap = registerCenter4Consumer
                            .getServiceMetaDataMap4Consume();
                    if (MapUtils.isEmpty(providerMap)) {
                        throw new RuntimeException("service provider list is empty.");
                    }

                    NettyChannelFactory.channelFactoryInstance().initChannelPoolFactory(providerMap);
                }
                ((RegisterCenter)registerCenter4Consumer).setInit(true);
            }
        }

        InvokerService invoker = new InvokerService();
        invoker.setServiceItf(targetInterface);
        invoker.setRemoteAppKey(remoteAppKey);
        invoker.setGroupName(groupName);
        registerCenter4Consumer.registerInvoker(invoker);
    }

    public static class Builder{
        /**
         * 需要调用的服务的接口
         */
        private Class<?> targetInterface;
        /**
         * socket
         */
        private ProviderService providerService;

        /**
         * 负载均衡策略
         */
        private String clusterStrategy;

        public Builder(){

        }

        public Builder targetInterface(Class<?> targetInterface){
            this.targetInterface = targetInterface;
            return this;
        }

        public Builder providerService(ProviderService providerService){
            this.providerService = providerService;
            return this;
        }

        public Builder clusterStrategy(String clusterStrategy){
            this.clusterStrategy = clusterStrategy;
            return this;
        }

        public ZKConnect build(){
            return new ZKConnect(this);
        }
    }
}
